'use strict'

let myUtil = require('./util');

let vercodes = new Map();
let vercodeConfig = {
    timeLimit: 60 * 1000,
    timeout: 30 * 60 * 1000,
    gcInterval: 10 * 6 * 1000
};

function prepare(telephone) {
    if ( !telephone ) {
        return null;
    }

    let now = myUtil.currentTimestamp();

    let vercode = {
        code: myUtil.randomString(4),
        timeout: now + vercodeConfig.timeout,
        nextTime: now + vercodeConfig.timeLimit
    };

    vercodes.set(telephone, vercode);

    return vercode.code;
}

function canPrepare(telephone) {
    if ( !telephone ) {
        return false;
    }

    if ( !vercodes.has(telephone) ) {
        return true;
    }

    let vercode = vercodes.get(telephone);
    if ( vercode.nextTime < myUtil.currentTimestamp() ) {
        return true;
    }

    return false;
}

function verify(telephone, code) {
    if ( !telephone ) {
        return false;
    }

    if ( !code ) {
        return false;
    }

    let now = myUtil.currentTimestamp();
    if ( !vercodes.has(telephone) ) {
        return false;
    }

    let existedVercode = vercodes.get(telephone);
    if ( existedVercode.timeout > myUtil.currentTimestamp() &&
            existedVercode.code == code ) {
        return true;
    }

    return false;
}

function gc() {
    let now = myUtil.currentTimestamp();

    vercodes.forEach((vercode, key) => {
        if ( vercode.timeout < now ) {
            vercodes.delete(key);
        }
    });
}
setInterval(gc, vercodeConfig.gcInterval);

module.exports = {
    vercodes,
    config: vercodeConfig,
    prepare,
    canPrepare,
    verify,
    gc,
    mock(mockModule) {
        if ( 'myUtil' in mockModule ) {
            myUtil = mockModule.myUtil;
        }
    }
};
